package com.hackordie.daos;

import java.util.ArrayList;
import java.util.List;

import com.hackordie.commons.hardware.components.AComponent;
import com.hackordie.commons.hardware.components.Firewall;
import com.hackordie.commons.hardware.components.HardDisk;
import com.hackordie.commons.hardware.components.NetworkCard;
import com.hackordie.commons.hardware.components.PowerSupply;
import com.hackordie.commons.hardware.components.Processor;
import com.hackordie.commons.hardware.components.RamMemory;
import com.hackordie.constants.EComponentsType;
import com.hackordie.daos.mappers.FirewallMapper;
import com.hackordie.daos.mappers.HardDiskMapper;
import com.hackordie.daos.mappers.NetworkCardMapper;
import com.hackordie.daos.mappers.PowerSupplyMapper;
import com.hackordie.daos.mappers.ProcessorMapper;
import com.hackordie.daos.mappers.RamMemoryMapper;

public class ComponentsDao extends ACommonDao<AComponent> {

	@Override
	public boolean create(final AComponent component) {
		String SQL = "INSERT INTO Components(name, energyTurnOn, prize) "     +
		                     "VALUES ('" + component.getComponentName() + "', " +
		                                  component.getEnergyToTurnOn()+ ", " +
			                              component.getPrice() +")";
				
		//update devuelve numero de filas afectadas
		//debe ser 1
		int result = jdbcTemplate.update(SQL);
		if(result == 1) {		
		    switch(component.getComponentType()) {
		    case Firewall: 
		        SQL = "INSERT INTO Firewalls (idComponent, difficultAccess) " +
		        		      "VALUES ( (SELECT idComponent " +
		        		                    "FROM Components " +
		        		                    "WHERE name = '" + component.getComponentName() + "' limit 1)," +
		        		                ((Firewall)component).getDificultAccess() + ");";
		        break;		    
		    case HardDisk: 
		        SQL = "INSERT INTO HardDisks (idComponent, capacity) " +
                        "VALUES ( (SELECT idComponent " +
                                      "FROM Components " +
                                      "WHERE name = '" + component.getComponentName() + "' limit 1)," +
                                  ((HardDisk)component).getTotalCapacity() + ");";
		        
		        break;		 
		    case NetworkCard: 
		        SQL = "INSERT INTO NetworkCards (idComponent, speedConection) " +
                        "VALUES ( (SELECT idComponent " +
                                      "FROM Components " +
                                      "WHERE name = '" + component.getComponentName() + "' limit 1)," +
                                  ((NetworkCard)component).getSpeedConection() + ");";
		        break;		    
		    case PowerSupply:
		        SQL = "INSERT INTO PowerSupplies (idComponent, capacity) " +
                        "VALUES ( (SELECT idComponent " +
                                      "FROM Components " +
                                      "WHERE name = '" + component.getComponentName() + "' limit 1)," +
                                  ((PowerSupply)component).getGeneratedEnergy() + ");";
		        break;
		    case Processor:
		        SQL = "INSERT INTO Processors (idComponent, speedForCore, cores) " +
                        "VALUES ( (SELECT idComponent " +
                                      "FROM Components " +
                                      "WHERE name = '" + component.getComponentName() + "' limit 1)," +
                                  ((Processor)component).getSpeedForCore() + ", " + 
                                  ((Processor)component).getCores() + ");";
		        break;
		    case RamMemory:
		        SQL = "INSERT INTO Rams (idComponent, capacity) " +
                        "VALUES ( (SELECT idComponent " +
                                      "FROM Components " +
                                      "WHERE name = '" + component.getComponentName() + "' limit 1)," +
                                  ((RamMemory)component).getTotalCapacity() + ");";
		        break;
		}
				
		result = jdbcTemplate.update(SQL);
		if(result == 1) {
		    return true;
		}
		}
		return false;
	}

	public boolean delete(final String componentName) {
	    String SQL = "SELECT idComponent FROM components WHERE name = '" + componentName + "'";
	   
	    int idComponent = jdbcTemplate.queryForInt(SQL);
	    
		SQL = "DELETE FROM Components WHERE idComponent = " + idComponent;
		if(jdbcTemplate.update(SQL) == 1) {
		    return true;
		}
		return false;
	}

	public boolean update(final int idComponent, final AComponent component) {
		String SQL = "UPDATE Components";
		boolean coma = false;
		
		 switch(component.getComponentType()) {
         case Firewall:      
             SQL += ", firewalls";         
             break;      
         case HardDisk: 
             SQL += ", HardDisks";         
             break;
         case NetworkCard:       
             SQL += ", NetworkCards";         
             break;   
         case PowerSupply:   
             SQL += ", PowerSupplies";         
             break;    
         case Processor:     
             SQL += ", Processors";         
             break;      
         case RamMemory:    
             SQL += ", Rams";         
             break;      
		 }
		 
         SQL += " Set";
         
         if(!(component.getComponentName().equals(""))) {
             SQL += " name = '" + component.getComponentName() + "'";
             coma = true;
         }
         
         if(!(component.getEnergyToTurnOn() == -1)) {
             if(coma) {
                 SQL += ", ";  
             }             
             SQL += " energyTurnOn = " + component.getEnergyToTurnOn();
             coma = true;
         }
         
         if(!(component.getPrice() == -1)) {
             if(coma) {
                 SQL += ", ";
             }
             SQL += " prize = " + component.getPrice();
             coma = true;
         }
                  		 
         switch(component.getComponentType()) {
         case Firewall:      
             if(!( ((Firewall)component).getDificultAccess() == -1) ) {
                 if(coma) {
                     SQL += ", ";
                 }
                 SQL += " difficultAccess = " + ((Firewall)component).getDificultAccess();
                 coma = true;
             }
             SQL += " WHERE Components.idComponent = " + idComponent;
             if(!( ((Firewall)component).getDificultAccess() == -1) ) {
                 SQL += " and";
                 SQL += " Components.idComponent = Firewalls.idComponent";
             }
             break;      
         case HardDisk:    
             if(!( ((HardDisk)component).getTotalCapacity() == -1) ) {
                 if(coma) {
                     SQL += ", ";
                 }
                 SQL += " capacity = " + ((HardDisk)component).getTotalCapacity();  
                 coma = true;
             }
             SQL += " WHERE Components.idComponent = " + idComponent;
             if(!( ((HardDisk)component).getTotalCapacity() == -1) ) {
                 SQL += " and";
                 SQL += " Components.idComponent = HardDisks.idComponent";
             }
             break;    
         case NetworkCard:    
             if(!( ((NetworkCard)component).getSpeedConection() == -1) ) {
                 if(coma) {
                     SQL += ", ";
                 }
                 SQL += " speedConection = " + ((NetworkCard)component).getSpeedConection();  
                 coma = true;
             }
             SQL += " WHERE Components.idComponent = " + idComponent;
             if(!( ((NetworkCard)component).getSpeedConection() == -1) ) {
                 SQL += " and";
                 SQL += " Components.idComponent = NetworkCards.idComponent";
             }
             break;      
         case PowerSupply:      
             if(!( ((PowerSupply)component).getGeneratedEnergy() == -1) ) {
                 if(coma) {
                     SQL += ", ";
                 }
                 SQL += " capacity = " + ((PowerSupply)component).getGeneratedEnergy();  
                 coma = true;
             }
             SQL += " WHERE Components.idComponent = " + idComponent;
             if(!( ((PowerSupply)component).getGeneratedEnergy() == -1) ) {
                 SQL += " and";
                 SQL += " Components.idComponent = PowerSupplies.idComponent";
             }
             break;      
         case Processor:       
             if(!( ((Processor)component).getSpeedForCore() == -1) ) {
                 if(coma) {
                     SQL += ", ";
                 }
                 SQL += " speedForCore = " + ((Processor)component).getSpeedForCore(); 
                 coma = true;
             }
             if(!( ((Processor)component).getCores() == -1) ) {
                 if(coma) {
                     SQL += ", ";
                 }
                 SQL += " cores = " + ((Processor)component).getCores();  
                 coma = true;
             }
             SQL += " WHERE Components.idComponent = " + idComponent;
             if( (!( ((Processor)component).getSpeedForCore() == -1)) || 
                 (!( ((Processor)component).getCores() == -1)       )   ) {
                 SQL += " and";
                 SQL += " Components.idComponent = Processors.idComponent";
             }
             break;        
         case RamMemory:    
             if(!( ((RamMemory)component).getTotalCapacity() == -1) ) {
                 if(coma) {
                     SQL += ", ";
                 }
                 SQL += " capacity = " +((RamMemory)component).getTotalCapacity(); 
                 coma = true;
             }
             SQL += " WHERE Components.idComponent = " + idComponent;
             if(!( ((RamMemory)component).getTotalCapacity() == -1) ) {
                 SQL += " and";
                 SQL += " Components.idComponent = Rams.idComponent";
             }
             break;
       }
         
       int result = jdbcTemplate.update(SQL);
       
       //result deberia ser uno o dos, ya que se pueden updatear una fila de la tabla 
       //"components" o simultaneamente una fila de la tabla "Components" y una fila 
       //de la tabla correspondiente al tipo de componente (Firewalls, HardDisks, etc)
       if(result > 0 && result < 3) {
		return true;
       }
       return false;
	}


    public List<AComponent> getAllComponentsList() {
        
        List<AComponent> allComponents = new ArrayList<AComponent>();
 
        Firewall[] allFirewalls = getAllFirewalls();    
        HardDisk[] allHardDisks = getAllHardDisks();     
        NetworkCard[] allNetworkCards = getAllNetworkCards();       
        PowerSupply[] allPowerSupplies = getAllPowerSupplies();             
        RamMemory[] allRams = getAllRams();          
        Processor[] allPRocessors = getAllProcessors();
       
        for(int i = 0; i < allFirewalls.length; i++) {
            allComponents.add(allFirewalls[i]);
        }
        
        for(int i = 0; i < allHardDisks.length; i++) {
            allComponents.add(allHardDisks[i]);
        }
        
        for(int i = 0; i < allNetworkCards.length; i++) {
            allComponents.add(allNetworkCards[i]);
        }
        
        for(int i = 0; i < allPowerSupplies.length; i++) {
            allComponents.add(allPowerSupplies[i]);
        }
        
        for(int i = 0; i < allRams.length; i++) {
            allComponents.add(allRams[i]);
        }
        
        for(int i = 0; i < allPRocessors.length; i++) {
            allComponents.add(allPRocessors[i]);
        }
        
        return allComponents;
    }
    
    public Firewall[] getAllFirewalls() {
        
        final String SQL = "SELECT components.idComponent, " +
                           "name, " +
        		           "energyTurnOn, " +
        		           "prize, " +
        		           "difficultAccess " +
        		           "FROM components, firewalls " +
        		           "WHERE components.idComponent = firewalls.idComponent";
        
        return jdbcTemplate.query(SQL, new FirewallMapper()).toArray(new Firewall[] {}); 
    }
    
    public HardDisk[] getAllHardDisks() {
            
            final String SQL = "SELECT components.idComponent, " +
                               "name, " +
                               "energyTurnOn, " +
                               "prize, " +
                               "capacity " +
                               "FROM components, harddisks " +
                               "WHERE components.idComponent = harddisks.idComponent";
            
            return jdbcTemplate.query(SQL, new HardDiskMapper()).toArray(new HardDisk[] {}); 
        }
    
    public NetworkCard[] getAllNetworkCards() {
        
        final String SQL = "SELECT components.idComponent, " +
                           "name, " +
                           "energyTurnOn, " +
                           "prize, " +
                           "speedConection " +
                           "FROM components, networkCards " +
                           "WHERE components.idComponent = networkCards.idComponent";
        
        return jdbcTemplate.query(SQL, new NetworkCardMapper()).toArray(new NetworkCard[] {}); 
    }
    
    public PowerSupply[] getAllPowerSupplies() {
        
        final String SQL = "SELECT components.idComponent, " +
                           "name, " +
                           "energyTurnOn, " +
                           "prize, " +
                           "capacity " +
                           "FROM components, powerSupplies " +
                           "WHERE components.idComponent = powerSupplies.idComponent";
        
        return jdbcTemplate.query(SQL, new PowerSupplyMapper()).toArray(new PowerSupply[] {}); 
    }
    
    public RamMemory[] getAllRams() {
        
        final String SQL = "SELECT components.idComponent, " +
                           "name, " +
                           "energyTurnOn, " +
                           "prize, " +
                           "capacity " +
                           "FROM components, Rams " +
                           "WHERE components.idComponent = Rams.idComponent";
        
        return jdbcTemplate.query(SQL, new RamMemoryMapper()).toArray(new RamMemory[] {}); 
    }
    
    public Processor[] getAllProcessors() {
        
        final String SQL = "SELECT components.idComponent, " +
                           "name, " +
                           "energyTurnOn, " +
                           "prize, " +
                           "speedForCore, " +
                           "cores " +
                           "FROM components, processors " +
                           "WHERE components.idComponent = processors.idComponent";
        
        return jdbcTemplate.query(SQL, new ProcessorMapper()).toArray(new Processor[] {}); 
    }

    public AComponent get(final String componentName, final EComponentsType componentType) {
        String SQL = "SELECT idComponent FROM components WHERE name = '" + componentName + "'";        
        int idComponent = jdbcTemplate.queryForInt(SQL);
        
        SQL = "SELECT * FROM Components";
        
        switch(componentType) {
        case Firewall:
            SQL += ", Firewalls";
            break;
        case HardDisk:
            SQL += ", HardDisks";
            break;
        case RamMemory:
            SQL += ", Rams";
            break;
        case PowerSupply:
            SQL += ", PowerSupplies";
            break;
        case NetworkCard:
            SQL += ", networkCards";
            break;
        case Processor:
            SQL += ", Processors";
            break;
        }

        SQL += " WHERE Components.idCOmponent = ?";
        
        switch(componentType) {
        case Firewall:
            SQL += " AND Components.idCOmponent =  Firewalls.idComponent";
            return jdbcTemplate.queryForObject(SQL, new FirewallMapper(), idComponent);
        case HardDisk:
            SQL += " AND Components.idCOmponent =  HardDisks.idComponent";
            return jdbcTemplate.queryForObject(SQL, new HardDiskMapper(), idComponent);
        case RamMemory:
            SQL += " AND Components.idCOmponent =  Rams.idComponent";
            return jdbcTemplate.queryForObject(SQL, new RamMemoryMapper(), idComponent);
        case PowerSupply:
            SQL += " AND Components.idCOmponent =  PowerSupplies.idComponent";
            return jdbcTemplate.queryForObject(SQL, new PowerSupplyMapper(), idComponent);
        case NetworkCard:
            SQL += " AND Components.idCOmponent =  NetworkCards.idComponent";
            return jdbcTemplate.queryForObject(SQL, new NetworkCardMapper(), idComponent);
        case Processor:
            SQL += " AND Components.idCOmponent =  Processors.idComponent";
            return jdbcTemplate.queryForObject(SQL, new ProcessorMapper(), idComponent);
        }
        return null;        
    }
    
    @Override
    public AComponent get(int id) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean delete(int id) {
        final String SQL = "DELETE FROM Components WHERE idComponent = " + id;
        if(jdbcTemplate.update(SQL) == 1) {
            return true;
        }
        return false;
    }

    @Override
    public boolean update(AComponent entity) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public AComponent[] getAll() {
        // TODO Auto-generated method stub
        return null;
    }

    public int countAll() {
        return getAllComponentsList().size();
    }

    
   
}
